const { MiniProgram, User, SystemLog } = require('../models');
const { AppError } = require('../middlewares/errorHandler');
const { logger } = require('../utils/logger');
const { Op } = require('sequelize');

class MiniProgramController {
  /**
   * 创建小程序
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async createMiniProgram(ctx) {
    const {
      name,
      appId,
      appSecret,
      config,
      description,
      domain,
      serverDomain,
      paymentConfig,
      templateIds,
      version
    } = ctx.request.body;
    const userId = ctx.state.user.id;

    // Check if mini program already exists
    const existingProgram = await MiniProgram.findOne({
      where: {
        [Op.or]: [
          { name },
          { appId }
        ]
      }
    });

    if (existingProgram) {
      throw new AppError(400, 'Mini program with this name or appId already exists');
    }

    // Create mini program
    const miniProgram = await MiniProgram.create({
      name,
      appId,
      appSecret,
      config,
      description,
      domain,
      serverDomain,
      paymentConfig,
      templateIds,
      version,
      status: 'active',
      qrCodes: {},
      statistics: {
        totalUsers: 0,
        dailyActiveUsers: 0,
        monthlyActiveUsers: 0
      }
    });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'create_mini_program',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Mini program created: ${name}`
    });

    ctx.status = 201;
    ctx.body = {
      status: 'success',
      data: { miniProgram }
    };
  }

  async updateMiniProgram(ctx) {
    const { id } = ctx.params;
    const {
      name,
      appSecret,
      config,
      description,
      domain,
      serverDomain,
      paymentConfig,
      templateIds,
      version,
      status
    } = ctx.request.body;
    const userId = ctx.state.user.id;

    const miniProgram = await MiniProgram.findByPk(id);
    if (!miniProgram) {
      throw new AppError(404, 'Mini program not found');
    }

    // Check if new name already exists
    if (name && name !== miniProgram.name) {
      const existingProgram = await MiniProgram.findOne({
        where: {
          name,
          id: { [Op.ne]: id }
        }
      });
      if (existingProgram) {
        throw new AppError(400, 'Mini program with this name already exists');
      }
    }

    // Update mini program
    await miniProgram.update({
      name,
      appSecret,
      config,
      description,
      domain,
      serverDomain,
      paymentConfig,
      templateIds,
      version,
      status
    });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'update_mini_program',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Mini program updated: ${name}`
    });

    ctx.body = {
      status: 'success',
      data: { miniProgram }
    };
  }

  /**
   * 删除小程序
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async deleteMiniProgram(ctx) {
    const { id } = ctx.params;
    const userId = ctx.state.user.id;

    const miniProgram = await MiniProgram.findByPk(id);
    if (!miniProgram) {
      throw new AppError(404, 'Mini program not found');
    }

    // Remove user associations
    await miniProgram.setUsers([]);
    
    await miniProgram.destroy();

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'delete_mini_program',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Mini program deleted: ${miniProgram.name}`
    });

    ctx.body = {
      status: 'success',
      message: 'Mini program deleted successfully'
    };
  }

  /**
   * 获取小程序列表
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getMiniPrograms(ctx) {
    const { status } = ctx.query;
    const where = {};

    if (status) where.status = status;

    const miniPrograms = await MiniProgram.findAll({
      where,
      attributes: { exclude: ['appSecret'] }
    });

    ctx.body = {
      status: 'success',
      data: { miniPrograms }
    };
  }

  /**
   * 获取单个小程序
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getMiniProgram(ctx) {
    const { id } = ctx.params;

    const miniProgram = await MiniProgram.findByPk(id, {
      attributes: { exclude: ['appSecret'] },
      include: [{
        model: User,
        attributes: ['id', 'username', 'email'],
        through: { attributes: [] }
      }]
    });

    if (!miniProgram) {
      throw new AppError(404, 'Mini program not found');
    }

    ctx.body = {
      status: 'success',
      data: { miniProgram }
    };
  }

  /**
   * 更新小程序状态
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updateMiniProgramStatus(ctx) {
    const { id } = ctx.params;
    const { status } = ctx.request.body;
    const userId = ctx.state.user.id;

    const miniProgram = await MiniProgram.findByPk(id);
    if (!miniProgram) {
      throw new AppError(404, '小程序不存在');
    }

    // 验证状态值
    const validStatuses = ['active', 'inactive', 'maintenance', 'deprecated'];
    if (!validStatuses.includes(status)) {
      throw new AppError(400, '无效的状态值');
    }

    await miniProgram.update({ 
      status,
      updatedBy: userId,
      lastStatusChange: new Date()
    });

    // 记录操作日志
    await SystemLog.create({
      action: 'update_mini_program_status',
      operator: userId,
      target_type: 'mini_program',
      target_id: id,
      details: { 
        before: miniProgram.status,
        after: status
      }
    });

    ctx.body = {
      status: 'success',
      data: {
        miniProgram
      }
    };
  }

  /**
   * 更新小程序二维码
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updateQRCodes(ctx) {
    const { id } = ctx.params;
    const { qrCodes } = ctx.request.body;
    const userId = ctx.state.user.id;

    const miniProgram = await MiniProgram.findByPk(id);
    if (!miniProgram) {
      throw new AppError(404, 'Mini program not found');
    }

    await miniProgram.update({ qrCodes });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'update_mini_program_qrcodes',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Mini program ${miniProgram.name} QR codes updated`
    });

    ctx.body = {
      status: 'success',
      data: { miniProgram }
    };
  }

  /**
   * 更新小程序统计数据
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updateStatistics(ctx) {
    const { id } = ctx.params;
    const { statistics } = ctx.request.body;
    const userId = ctx.state.user.id;

    const miniProgram = await MiniProgram.findByPk(id);
    if (!miniProgram) {
      throw new AppError(404, 'Mini program not found');
    }

    await miniProgram.update({ statistics });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'update_mini_program_statistics',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Mini program ${miniProgram.name} statistics updated`
    });

    ctx.body = {
      status: 'success',
      data: { miniProgram }
    };
  }

  /**
   * 分配小程序用户
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async assignUser(ctx) {
    const { id } = ctx.params;
    const { userId: targetUserId } = ctx.request.body;
    const operatorId = ctx.state.user.id;

    const miniProgram = await MiniProgram.findByPk(id);
    if (!miniProgram) {
      throw new AppError(404, 'Mini program not found');
    }

    const user = await User.findByPk(targetUserId);
    if (!user) {
      throw new AppError(404, 'User not found');
    }

    await miniProgram.addUser(user);

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'assign_mini_program_user',
      userId: operatorId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `User ${user.username} assigned to mini program ${miniProgram.name}`
    });

    ctx.body = {
      status: 'success',
      message: 'User assigned successfully'
    };
  }

  /**
   * 移除小程序用户
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async removeUser(ctx) {
    const { id, userId: targetUserId } = ctx.params;
    const operatorId = ctx.state.user.id;

    const miniProgram = await MiniProgram.findByPk(id);
    if (!miniProgram) {
      throw new AppError(404, 'Mini program not found');
    }

    const user = await User.findByPk(targetUserId);
    if (!user) {
      throw new AppError(404, 'User not found');
    }

    await miniProgram.removeUser(user);

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'remove_mini_program_user',
      userId: operatorId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `User ${user.username} removed from mini program ${miniProgram.name}`
    });

    ctx.body = {
      status: 'success',
      message: 'User removed successfully'
    };
  }
}

module.exports = new MiniProgramController(); 